package com.gome.ocean.service.velocity;

import java.io.StringReader;
import java.io.StringWriter;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;

import org.apache.commons.lang.StringUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.log.CommonsLogLogChute;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

import com.gome.ocean.common.constants.DataxContants;
import com.gome.ocean.common.constants.VelocityContants;
import com.gome.ocean.common.enums.job.JobLimit;
import com.gome.ocean.common.enums.job.Reader;
import com.gome.ocean.common.enums.job.Writer;
import com.gome.ocean.common.exception.VelocityNotSupportException;
import com.gome.ocean.common.exception.VelocityParamsException;
import com.gome.ocean.common.utils.TimeUtils;
import com.gome.ocean.dao.model.gddl.GddlShardAppVO;

/**
 * 插件文件
 * 
 * @author haqiaolong 2016年1月20日 下午3:39:06
 * @since 5.0.0
 */
@Component
public class VelocityBean implements InitializingBean, DisposableBean {

    private static VelocityEngine velocityEngine = new VelocityEngine();

    @Override
    public void destroy() throws Exception {
        if (velocityEngine != null) {
            velocityEngine = null;
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        Properties properties = new Properties();
        properties.put(VelocityEngine.FILE_RESOURCE_LOADER_PATH,
            this.getClass().getResource(DataxContants.DEFAULT_DATAX_TEMPLATE).getPath()); // 设置模板目录
        velocityEngine.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM, new CommonsLogLogChute()); // 统一日志
        velocityEngine.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_CACHE, "true"); // 缓存
        velocityEngine.setProperty(RuntimeConstants.INPUT_ENCODING, VelocityContants.DEFAULT_TEMPLATE_CHARSET);
        velocityEngine.setProperty(RuntimeConstants.OUTPUT_ENCODING, VelocityContants.DEFAULT_TEMPLATE_CHARSET);
        velocityEngine.init(properties);
    }

    public String assemblePlugins(Reader reader, Map<String, Object> readerMaps, Writer writer,
                                  Map<String, Object> writerMaps, JobLimit jobLimit, Long limitValue) {
        if (reader == null || writer == null) {
            throw new VelocityParamsException("模板生成参数错误!");
        }
        Template readerPlugin = null;
        if (Reader.DRDS == reader) {
            readerPlugin = velocityEngine.getTemplate(VelocityContants.DRDSREADER);
        } else if (Reader.MONGODB == reader) {
            readerPlugin = velocityEngine.getTemplate(VelocityContants.MONGODBREADER);
        } else if (Reader.MYSQL == reader) {
            readerPlugin = velocityEngine.getTemplate(VelocityContants.MYSQLREADER);
        } else if (Reader.ORACLE == reader) {
            readerPlugin = velocityEngine.getTemplate(VelocityContants.ORACLEREADER);
        } else if (Reader.HBASE == reader) {
            readerPlugin = velocityEngine.getTemplate(VelocityContants.HBASEREADER);
        } else if (Reader.HDFS == reader) {
            readerPlugin = velocityEngine.getTemplate(VelocityContants.HDFSREADER);
        } else if(Reader.SQLSERVER == reader){
            readerPlugin = velocityEngine.getTemplate(VelocityContants.SQLSERVERREADER);
        }else{
            throw new VelocityNotSupportException("不支持读取插件! :" + reader);
        }
        Template writerPlugin = null;
        if (Writer.DRDS == writer) {
            writerPlugin = velocityEngine.getTemplate(VelocityContants.DRDSWRITER);
        } else if (Writer.MONGODB == writer) {
            writerPlugin = velocityEngine.getTemplate(VelocityContants.MONGODBWRITER);
        } else if (Writer.MYSQL == writer) {
            writerPlugin = velocityEngine.getTemplate(VelocityContants.MYSQLWRITER);
        } else if (Writer.ORACLE == writer) {
            writerPlugin = velocityEngine.getTemplate(VelocityContants.ORACLEWRITER);
        } else if (Writer.STREAM == writer) {
            writerPlugin = velocityEngine.getTemplate(VelocityContants.STREAMWRITER);
        } else if (Writer.HDFS == writer) {
            writerPlugin = velocityEngine.getTemplate(VelocityContants.HDFSWRITER);
        } else if (Writer.REDIS == writer) {
            writerPlugin = velocityEngine.getTemplate(VelocityContants.REDISWRITER);
        } else {
            throw new VelocityNotSupportException("不支持写入插件! :" + writer);
        }
        if (readerPlugin == null || writerPlugin == null) {
            throw new VelocityParamsException("模板生成参数错误!");
        }
        VelocityContext readwriterContext = new VelocityContext();

        StringWriter readerWriter = new StringWriter();
        readerPlugin.merge(convertVelocityContext(readerMaps), readerWriter);
        readwriterContext.put("reader", readerWriter.toString());

        readerWriter = new StringWriter();
        writerPlugin.merge(convertVelocityContext(writerMaps), readerWriter);
        readwriterContext.put("writer", readerWriter.toString());

        Template readerWriterPlugin = velocityEngine.getTemplate(VelocityContants.READWRITECOMMON);
        readerWriter = new StringWriter();
        if (jobLimit == null) {
            readwriterContext.put(VelocityContants.BYTE, DataxContants.DEFAULT_BYTE_SIZE);
        } else {
            if (JobLimit.BYTES == jobLimit) {
                readwriterContext.put(VelocityContants.BYTE, limitValue);
            } else if (JobLimit.RECORD == jobLimit) {
                readwriterContext.put(VelocityContants.RECORD, limitValue);
            }
        }
        readerWriterPlugin.merge(readwriterContext, readerWriter);
        return readerWriter.toString();
    }

    /**
     * 根据指定模板生成文件
     * 
     * @param templateName
     * @param paramMaps
     * @return
     */
    public String assemblePlugins(String templateName, Map<String, Object> paramMaps) {
        if (StringUtils.isEmpty(templateName) || paramMaps == null) {
            throw new VelocityParamsException("模板生成参数错误!");
        }
        Template templatePlugin = velocityEngine.getTemplate(templateName);
        StringWriter templateWriter = new StringWriter();
        templatePlugin.merge(convertVelocityContext(paramMaps), templateWriter);
        return templateWriter.toString();
    }
    public String assemblePlugins(String templateName,List<GddlShardAppVO> list) {
        if (StringUtils.isEmpty(templateName) || list == null) {
            throw new VelocityParamsException("模板生成参数错误!");
        }
        Template templatePlugin = velocityEngine.getTemplate(templateName);
        StringWriter templateWriter = new StringWriter();
        VelocityContext context = new VelocityContext();
        context.put("list", list);
        templatePlugin.merge(context, templateWriter);
        return templateWriter.toString();
    }
    /**
     * 处理jobContext where条件 增加 today(今天) yesterday(昨天) tomorrow(明天)
     * 
     * @param jobContext
     * @return
     */
    public String processJobContext(String jobContext) {
        if (StringUtils.isEmpty(jobContext)) return jobContext;
        VelocityContext readwriterContext = new VelocityContext();
        readwriterContext.put(VelocityContants.TODAY, TimeUtils.today());
        readwriterContext.put(VelocityContants.YESTERDAY, TimeUtils.yesterday());
        readwriterContext.put(VelocityContants.TOMORROW, TimeUtils.tomorrow());

        StringWriter readerWriter = new StringWriter();
        StringReader stringReader = new StringReader(jobContext);
        velocityEngine.evaluate(readwriterContext, readerWriter, "velocity_evaluate", stringReader);
        return readerWriter.toString();

    }

    /**
     * 处理邮件内容
     * 
     * @param emailContext
     * @param params
     * @return
     */
    public String processEmailContext(String emailContext, Map<String, String> contextMaps) {
        if (StringUtils.isEmpty(emailContext)) return emailContext;
        VelocityContext readwriterContext = new VelocityContext();
        for (Entry<String, String> param : contextMaps.entrySet()) {
            readwriterContext.put(param.getKey(), param.getValue());
        }
        StringWriter readerWriter = new StringWriter();
        StringReader stringReader = new StringReader(emailContext);
        velocityEngine.evaluate(readwriterContext, readerWriter, "velocity_evaluate", stringReader);
        return readerWriter.toString();
    }

    /**
     * 生成yugong配置内容
     * 
     * @param map
     * @return
     */
    public String generateYugongProps(Map<String, Object> map) {

        Template ygConfTemplate = velocityEngine.getTemplate(VelocityContants.YUGONG_PROPERTIES);

        StringWriter readerWriter = new StringWriter();
        ygConfTemplate.merge(convertVelocityContext(map), readerWriter);

        return readerWriter.toString();
    }

    /**
     * 转换Map为VelocityContext
     * 
     * @param map
     * @return
     */
    private VelocityContext convertVelocityContext(Map<String, Object> paramMaps) {
        VelocityContext context = new VelocityContext();
        if (paramMaps == null || paramMaps.isEmpty()) {
            return context;
        }
        for (Map.Entry<String, Object> entry : paramMaps.entrySet()) {
            context.put(entry.getKey(), entry.getValue());
        }
        return context;
    }

}
